//! # CLI 配置管理
//!
//! 管理 CLI 工具的配置文件和全局设置

use crate::error::{CliError, CliResult};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use tokio::fs;

/// CLI 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CliConfig {
    /// 全局设置
    pub global: GlobalConfig,
    /// 模板设置
    pub templates: TemplateConfig,
    /// 部署设置
    pub deploy: DeployConfig,
    /// 插件设置
    pub plugins: PluginConfig,
    /// 用户自定义设置
    pub custom: HashMap<String, serde_json::Value>,
}

/// 全局配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlobalConfig {
    /// 默认作者信息
    pub author: AuthorInfo,
    /// 默认仓库设置
    pub repository: RepositoryConfig,
    /// 编辑器设置
    pub editor: String,
    /// 语言偏好
    pub language: String,
    /// 自动更新检查
    pub auto_update_check: bool,
    /// 缓存目录
    pub cache_dir: Option<PathBuf>,
    /// 临时目录
    pub temp_dir: Option<PathBuf>,
}

/// 作者信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthorInfo {
    /// 姓名
    pub name: String,
    /// 邮箱
    pub email: String,
    /// 组织
    pub organization: Option<String>,
}

/// 仓库配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepositoryConfig {
    /// 默认仓库提供商
    pub provider: String,
    /// 仓库基础 URL
    pub base_url: Option<String>,
    /// 许可证
    pub license: String,
    /// 是否私有
    pub private: bool,
}

/// 模板配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateConfig {
    /// 模板仓库 URL
    pub repository_url: String,
    /// 本地模板目录
    pub local_dir: Option<PathBuf>,
    /// 缓存过期时间（小时）
    pub cache_expires_hours: u64,
    /// 自定义模板
    pub custom_templates: HashMap<String, TemplateInfo>,
}

/// 模板信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateInfo {
    /// 模板路径或 URL
    pub source: String,
    /// 描述
    pub description: String,
    /// 版本
    pub version: Option<String>,
    /// 标签
    pub tags: Vec<String>,
}

/// 部署配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeployConfig {
    /// 默认环境
    pub default_environment: String,
    /// 环境配置
    pub environments: HashMap<String, EnvironmentConfig>,
    /// Docker 设置
    pub docker: DockerConfig,
    /// Kubernetes 设置
    pub kubernetes: KubernetesConfig,
}

/// 环境配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnvironmentConfig {
    /// 描述
    pub description: String,
    /// 部署目标
    pub target: String,
    /// 配置文件
    pub config_file: Option<PathBuf>,
    /// 环境变量
    pub env_vars: HashMap<String, String>,
    /// 部署前钩子
    pub pre_deploy: Vec<String>,
    /// 部署后钩子
    pub post_deploy: Vec<String>,
}

/// Docker 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DockerConfig {
    /// 镜像仓库
    pub registry: String,
    /// 命名空间
    pub namespace: String,
    /// 基础镜像
    pub base_image: String,
    /// 构建参数
    pub build_args: HashMap<String, String>,
}

/// Kubernetes 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KubernetesConfig {
    /// 默认命名空间
    pub default_namespace: String,
    /// 上下文
    pub context: Option<String>,
    /// 配置文件路径
    pub config_path: Option<PathBuf>,
    /// Helm 设置
    pub helm: HelmConfig,
}

/// Helm 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HelmConfig {
    /// Chart 仓库
    pub repository: String,
    /// 发布名称前缀
    pub release_prefix: String,
    /// 值文件目录
    pub values_dir: Option<PathBuf>,
}

/// 插件配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginConfig {
    /// 已安装插件
    pub installed: HashMap<String, PluginInfo>,
    /// 插件仓库
    pub repositories: Vec<String>,
    /// 启用的插件
    pub enabled: Vec<String>,
}

/// 插件信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginInfo {
    /// 版本
    pub version: String,
    /// 安装路径
    pub path: PathBuf,
    /// 描述
    pub description: String,
    /// 作者
    pub author: String,
}

impl Default for CliConfig {
    fn default() -> Self {
        Self {
            global: GlobalConfig::default(),
            templates: TemplateConfig::default(),
            deploy: DeployConfig::default(),
            plugins: PluginConfig::default(),
            custom: HashMap::new(),
        }
    }
}

impl Default for GlobalConfig {
    fn default() -> Self {
        Self {
            author: AuthorInfo::default(),
            repository: RepositoryConfig::default(),
            editor: "code".to_string(),
            language: "zh-CN".to_string(),
            auto_update_check: true,
            cache_dir: None,
            temp_dir: None,
        }
    }
}

impl Default for AuthorInfo {
    fn default() -> Self {
        Self {
            name: "Developer".to_string(),
            email: "developer@example.com".to_string(),
            organization: None,
        }
    }
}

impl Default for RepositoryConfig {
    fn default() -> Self {
        Self {
            provider: "github".to_string(),
            base_url: None,
            license: "MIT".to_string(),
            private: false,
        }
    }
}

impl Default for TemplateConfig {
    fn default() -> Self {
        Self {
            repository_url: "https://github.com/rustcloud/templates.git".to_string(),
            local_dir: None,
            cache_expires_hours: 24,
            custom_templates: HashMap::new(),
        }
    }
}

impl Default for DeployConfig {
    fn default() -> Self {
        Self {
            default_environment: "development".to_string(),
            environments: HashMap::new(),
            docker: DockerConfig::default(),
            kubernetes: KubernetesConfig::default(),
        }
    }
}

impl Default for DockerConfig {
    fn default() -> Self {
        Self {
            registry: "docker.io".to_string(),
            namespace: "rustcloud".to_string(),
            base_image: "rust:alpine".to_string(),
            build_args: HashMap::new(),
        }
    }
}

impl Default for KubernetesConfig {
    fn default() -> Self {
        Self {
            default_namespace: "default".to_string(),
            context: None,
            config_path: None,
            helm: HelmConfig::default(),
        }
    }
}

impl Default for HelmConfig {
    fn default() -> Self {
        Self {
            repository: "https://charts.rustcloud.io".to_string(),
            release_prefix: "rustcloud".to_string(),
            values_dir: None,
        }
    }
}

impl Default for PluginConfig {
    fn default() -> Self {
        Self {
            installed: HashMap::new(),
            repositories: vec![
                "https://plugins.rustcloud.io".to_string(),
            ],
            enabled: Vec::new(),
        }
    }
}

impl CliConfig {
    /// 从文件加载配置
    pub async fn from_file<P: AsRef<Path>>(path: P) -> CliResult<Self> {
        let content = fs::read_to_string(path).await?;
        let config: CliConfig = toml::from_str(&content)?;
        Ok(config)
    }

    /// 保存配置到文件
    pub async fn save_to_file<P: AsRef<Path>>(&self, path: P) -> CliResult<()> {
        let content = toml::to_string_pretty(self)
            .map_err(|e| CliError::general(format!("序列化配置失败: {}", e)))?;
        fs::write(path, content).await?;
        Ok(())
    }

    /// 加载默认配置
    pub async fn load_default() -> CliResult<Self> {
        let config_path = Self::default_config_path()?;
        if config_path.exists() {
            Self::from_file(config_path).await
        } else {
            // 创建默认配置文件
            let config = Self::default();
            if let Some(parent) = config_path.parent() {
                fs::create_dir_all(parent).await?;
            }
            config.save_to_file(&config_path).await?;
            Ok(config)
        }
    }

    /// 获取默认配置文件路径
    pub fn default_config_path() -> CliResult<PathBuf> {
        let home_dir = dirs::home_dir()
            .ok_or_else(|| CliError::config("无法获取用户主目录"))?;
        Ok(home_dir.join(".rustcloud").join("config.toml"))
    }

    /// 获取缓存目录
    pub fn cache_dir(&self) -> CliResult<PathBuf> {
        if let Some(cache_dir) = &self.global.cache_dir {
            Ok(cache_dir.clone())
        } else {
            let cache_dir = dirs::cache_dir()
                .ok_or_else(|| CliError::config("无法获取缓存目录"))?
                .join("rustcloud");
            Ok(cache_dir)
        }
    }

    /// 获取临时目录
    pub fn temp_dir(&self) -> CliResult<PathBuf> {
        if let Some(temp_dir) = &self.global.temp_dir {
            Ok(temp_dir.clone())
        } else {
            Ok(std::env::temp_dir().join("rustcloud"))
        }
    }
}